package com.yuelife.market.rabbitmq;

import com.rabbitmq.client.Channel;
import com.yuelife.market.dao.MOrderDao;
import com.yuelife.market.dao.MProductDao;
import com.yuelife.market.entity.MOrder;
import com.yuelife.market.entity.MProduct;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Map;

//死信消费，如果是被死信消费的订单，那么全部视为无效订单，修改数据库中的订单状态和商品状态，以及redis中的缓存
@Component
public class DeadOrderConsumer {
    @Autowired
    private MOrderDao mOrderDao;
    @Autowired
    private MProductDao mProductDao;
    @Autowired
    private RedisTemplate redisTemplate;

    //队列的监听
    @RabbitListener(queues = "waitpay-dead-queue")//只要 waitpay-dead-queue 这个队列里面有数据，就会调用下面这个方法 orderQueue方法进行处理
    //RabbitHandler 用来标明消费者处理消息的方法；@Payload注解用来标明这是一个消息参数（生产者发送过来的）@Headers注解：标明用来获取消息请求头中的数据，可以在请求头中获取到消息的id，可以用在签收那条消息
    @RabbitHandler
    @Transactional //由于操作了两个数据库，所以需要事务
    public void orderQueue(@Payload MOrder mOrder, Channel channel, @Headers Map headers){
        System.out.println("死信订单消息，签收看是否成功支付"+ mOrder.getOrderSn());

        //查询此时数据库中订单的状态，然后与死信队列中被消费的订单状态比较，如果是未支付状态的，那么就签收该消息，订单为无效订单
        //数据库中订单状态
        String m=mOrderDao.selectOrderStatusByOrderSn(mOrder.getOrderSn());

        //得到需要消费的消息id，
        Long id= (Long) headers.get(AmqpHeaders.DELIVERY_TAG);

        //判断一下此时被消费的订单状态是不是为支付状态的 0 就是未支付状态   1 已支付  3 已发货  4 已发货   6 超时失效
        if (m.equals("0")){
            try {//这里操作了两个数据库
//                //成为失效订单,修改订单状态
                mOrderDao.updateOrderStatusBySn(mOrder.getOrderSn(),6);
                //删除订单
//                mOrderDao.deleteBySn(mOrder.getOrderSn());
                //修改商品状态 1：已购买？0：无人购买？2：正在审核 3：没有通过审核
                mProductDao.updateStatusByProductSn(mOrder.getProductSn(),0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //还没有做支付宝成功之后，处理另外一个队列中的消息队列  明天来
            //数据库中查询商品信息
            MProduct mProduct=mProductDao.selectProductBySn(mOrder.getProductSn());
            //更新redis，因为订单失效了，把之前购买的商品，重新添加到redis中
            redisTemplate.opsForHash().put("myProductList",mProduct.getProductSn(),mProduct);
            try {
                //直接消费消息，签收，从队列中清除，
                channel.basicAck(id,false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            //如果支付成功之后，那么就在这里签收就行了，不更改数据库任何东西
            //直接签收，不签收的话，会在死信队列累计很多消息
            try {
                //直接消费消息，签收，从队列中清除，
                channel.basicAck(id,false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //问一下   这后面需不需要加什么else{return}，这样就结束了，感觉没有加的话  代码老是不完整  没有结束一样

    }



}
